home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / stdwin / Ports / mac / dialog.c < prev    next >
Text File  |  1995-12-21  |  9KB  |  407 lines

  1. /* MAC STDWIN -- DIALOGS. */
  2.  
  3. /* XXX These dialogs are distinctly ugly.
  4.    Maybe we should fix their size based on the amount of text
  5.    and the number of buttons. */
  6.  
  7. #include "macwin.h"
  8. #include <Dialogs.h>
  9. #include <Packages.h>
  10. #include <Memory.h>
  11. #include <StandardFile.h>
  12.  
  13. #ifndef HAVE_UNIVERSAL_HEADERS
  14. #define DlgHookUPP ProcPtr
  15. #define FileFilterUPP ProcPtr
  16. #define ModalFilterUPP ProcPtr
  17. #define NewModalFilterProc(x) ((ProcPtr)x)
  18. #endif
  19.  
  20. /* Function prototypes */
  21.  
  22. STATIC struct itemlist **mkitemlist _ARGS((void));
  23. STATIC struct item *finditem _ARGS((struct itemlist **h, int i));
  24. STATIC void additem _ARGS((struct itemlist **h,
  25.     long stuff, Rect *ppos, int type, int size, char *data));
  26. STATIC struct itemlist **ynclist _ARGS((char *prompt));
  27. STATIC struct itemlist **oklist _ARGS((char *prompt));
  28. STATIC struct itemlist **editlist _ARGS((char *prompt));
  29. STATIC int do_dialog _ARGS((struct itemlist **h,
  30.     int emphasis, int lastbutton, char *buf));
  31.  
  32. /* Mac-specific interface for applications that need different
  33.    file types */
  34. OSType std_type= 'TEXT';
  35.  
  36. OSType *wasktypelist= &std_type;
  37. int waskntypes= 1;
  38.  
  39. /* Standard File interface routine */
  40.  
  41. bool
  42. waskfile(prompt, buf, len, new)
  43.     char *prompt;
  44.     char *buf;
  45.     int len;
  46.     bool new;
  47. {
  48.     static Point corner= {80, 60};
  49.     SFReply reply;
  50.     
  51.     if (active != NULL)
  52.         rmcaret(active);
  53.     if (new) {
  54.         char *def= strrchr(buf, ':');
  55.         if (def != NULL)
  56.             ++def;
  57.         else
  58.             def= buf;
  59.         SFPutFile(PASSPOINT corner,
  60.             PSTRING(prompt),
  61. #ifdef CLEVERGLUE
  62.             PSTRING(def),
  63. #else
  64.             /* OK to overwrite contents of buf since it is
  65.                output anyway */
  66.             CtoPstr(def),
  67. #endif
  68.             (DlgHookUPP)NULL, &reply);
  69.     }
  70.     else {
  71.         SFGetFile(PASSPOINT corner,
  72.               (ConstStr255Param)NULL,
  73.               (FileFilterUPP)NULL,
  74.               waskntypes,
  75.               wasktypelist,
  76.               (DlgHookUPP)NULL,
  77.               &reply);
  78.     }
  79.     set_watch();
  80.     if (!reply.good)
  81.         return FALSE;
  82.     fullpath(buf, reply.vRefNum, PtoCstr(reply.fName));
  83.     return TRUE;
  84. }
  85.  
  86. /* Data definitions for dialog item lists (from Inside Mac). */
  87. /* XXXX Jack wonders why these aren't exported from the headers?? */
  88. #if GENERATINGPOWERPC
  89. #pragma options align=mac68k
  90. #endif
  91.  
  92. struct item {
  93.     long stuff;        /* Handle or proc pointer */
  94.     Rect pos;        /* Position (local coord.) */
  95.     char type;        /* Item type */
  96.     char size;        /* Length of data; must be even */
  97.     char data[256];     /* The data; variable length */
  98. };
  99.  
  100. struct itemlist {
  101.     short count;        /* Number of items minus one */
  102.     struct item data;    /* First item */
  103.     /* NB: items are variable length. */
  104. };
  105.  
  106. #if GENERATINGPOWERPC
  107. #pragma options align=reset
  108. #endif
  109.  
  110. #define ROUND_EVEN(x) (((x) + 1) & ~1) /* Round up to even */
  111.  
  112. #define FIXED_SIZE 14        /* Size of struct item w/o data */
  113.  
  114. /* Routines to manipulate Dialog item lists. */
  115.  
  116. /* Create an empty item list. */
  117.  
  118. static struct itemlist **
  119. mkitemlist()
  120. {
  121.     struct itemlist **h= (struct itemlist **) NewHandle(2);
  122.     
  123.     (*h)->count= -1;
  124.     return h;
  125. }
  126.  
  127. /* Find the i'th item, starting to count from 0.
  128.    It may be asked for the non-existing item just beyond the last,
  129.    but not beyond that. */
  130.  
  131. static struct item *
  132. finditem(h, i)
  133.     struct itemlist **h;
  134.     int i;
  135. {
  136.     int count= (*h)->count;
  137.     struct item *it= &(*h)->data;
  138.     int k;
  139.     
  140.     if (i < 0 || i > count+1) {
  141.         return NULL;
  142.     }
  143.     for (k= 0; k < i; ++k) {
  144.         /* I don't trust two casts in one expression: */
  145.         char *p= (char *) it;
  146.         int size= ROUND_EVEN(it->size);
  147.         p += FIXED_SIZE + size;
  148.         it= (struct item *) p;
  149.     }
  150.     return it;
  151. }
  152.  
  153. /* Add an item to the list. */
  154.  
  155. static void
  156. additem(h, stuff, ppos, type, size, data)
  157.     struct itemlist **h;
  158.     long stuff;
  159.     Rect *ppos;
  160.     int type;
  161.     int size;
  162.     char *data;
  163. {
  164.     struct item *it;
  165.     long totalsize;
  166.     
  167.     if (size < 0)
  168.         size= strlen(data);
  169.     it= finditem(h, (*h)->count + 1);
  170.     totalsize= (char *)it - (char *)(*h);
  171.     SetHandleSize((Handle)h, totalsize + FIXED_SIZE + ROUND_EVEN(size));
  172.     it= finditem(h, (*h)->count + 1);
  173.     it->stuff= stuff;
  174.     it->pos= *ppos;
  175.     it->type= type;
  176.     it->size= size;
  177.     BlockMove(data, it->data, size);
  178.     ++(*h)->count;
  179. }
  180.  
  181. /* Construct item list for question w/ Yes/No/Cancel response.
  182.    Note: the statText item is first, so we can distinguish between a
  183.    press on Return or Enter (when ModalDialog returns 1) and any
  184.    of the three buttons. */
  185.  
  186. static struct itemlist **
  187. ynclist(prompt)
  188.     char *prompt;
  189. {
  190.     struct itemlist **h= mkitemlist();
  191.     Rect pos;
  192.     
  193.     SetRect(&pos, 20, 20, 280, 70);
  194.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  195.     SetRect(&pos, 20, 80, 80, 100);
  196.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Yes");
  197.     OffsetRect(&pos, 0, 30);
  198.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "No");
  199.     OffsetRect(&pos, 200, 0);
  200.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Cancel");
  201.     return h;
  202. }
  203.  
  204. /* Construct item list for message w/ OK button. */
  205.  
  206. static struct itemlist **
  207. oklist(prompt)
  208.     char *prompt;
  209. {
  210.     struct itemlist **h= mkitemlist();
  211.     Rect pos;
  212.     
  213.     SetRect(&pos, 20, 20, 280, 100);
  214.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  215.     SetRect(&pos, 20, 110, 80, 130);
  216.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "OK");
  217.     return h;
  218. }
  219.  
  220. /* Construct item list for dialog w/ edit-text, OK and Cancel button. */
  221.  
  222. static struct itemlist **
  223. editlist(prompt)
  224.     char *prompt;
  225. {
  226.     struct itemlist **h= mkitemlist();
  227.     Rect pos;
  228.     
  229.     SetRect(&pos, 20, 20, 280, 70);
  230.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  231.     SetRect(&pos, 20, 110, 80, 130);
  232.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "OK");
  233.     OffsetRect(&pos, 200, 0);
  234.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Cancel");
  235.     SetRect(&pos, 20, 80, 280, 96);
  236.     additem(h, 0L, &pos, editText, 0, (char *) NULL);
  237.     return h;
  238. }
  239.  
  240. /* Filter procedure for ModalDialog, turns Return into hit of item #1.
  241.    XXX This used to be the default -- what happened?
  242. */
  243.  
  244. static pascal Boolean filter(d, e, hit)
  245.     DialogPtr d;
  246.     EventRecord *e;
  247.     short *hit;
  248. {
  249.     if (e->what == keyDown) {
  250.         char c = e->message & charCodeMask;
  251.         if (c == '\r' || c == ENTER_KEY) {
  252.             *hit = 1;
  253.             return 1;
  254.         }
  255.     }
  256.     return 0;
  257. }
  258.  
  259. /* Perform an entire dialog.
  260.    It stops when an item <= lastbutton is hit, and returns the item number.
  261.    When buf is non-NULL, the next item is assumed to be an edit-text
  262.    item and its contents are transferred to buf. */
  263.  
  264. static int
  265. do_dialog(h, emphasis, lastbutton, buf)
  266.     struct itemlist **h;
  267.     int emphasis;
  268.     int lastbutton;
  269.     char *buf;
  270. {
  271.     Rect box;
  272.     DialogPtr d;
  273.     short hit;
  274.     short type;
  275.     Handle item;
  276.     ModalFilterUPP filterupp = NewModalFilterProc(filter);
  277.     
  278.     _wresetmouse(); /* Clean up mouse down status */
  279.     if (active != NULL)
  280.         rmcaret(active);
  281.     
  282.     /* Create a box of convenient size, centered horizontally,
  283.        somewhat below the top of the screen. */
  284.     SetRect(&box, 0, 0, 300, 140);
  285.     OffsetRect(&box, (screen->portRect.right - box.right)/2, 60);
  286.     
  287.     d= NewDialog(
  288.         (Ptr)NULL,
  289.         &box,
  290.         (ConstStr255Param)"",
  291.         true,
  292.         dBoxProc,
  293.         (WindowPtr)(-1),
  294.         false,
  295.         0L,
  296.         (Handle)h);
  297.     
  298.     if (emphasis > 0) { /* Emphasize default button */
  299.         GetDItem(d, emphasis, &type, &item, &box);
  300.         SetPort(d);
  301.         InsetRect(&box, -4, -4);
  302.         PenSize(3, 3);
  303.         FrameRoundRect(&box, 16, 16);
  304.     }
  305.     
  306.     if (buf != NULL) { /* Set edit text and focus on entire text */
  307.         GetDItem(d, lastbutton+1, &type, &item, &box);
  308.         SetIText(item, PSTRING(buf));
  309.         SelIText(d, lastbutton+1, 0, 32000);
  310.     }
  311.     
  312.     set_arrow();
  313.     
  314.     /* XXX Should support Cmd-period as shortcut for Cancel;
  315.        perhaps other shortcuts as well? */
  316.     
  317.     do {
  318.         ModalDialog(filterupp, &hit);
  319.     } while (hit > lastbutton);
  320.     
  321.     set_watch();
  322.     
  323.     if (hit == 1 && emphasis > 0) {
  324.         /* Pressed Return or Enter; flash default button. */
  325.         GetDItem(d, emphasis, &type, &item, &box);
  326.         HiliteControl((ControlHandle)item, inButton);
  327.     }
  328.     
  329.     if (buf != NULL) {
  330.         GetDItem(d, lastbutton+1, &type, &item, &box);
  331.         GetIText(item, (unsigned char *)buf);
  332. #ifndef CLEVERGLUE
  333.         PtoCstr((unsigned char *)buf);
  334. #endif
  335.     }
  336.     DisposDialog(d);
  337.     return hit;
  338. }
  339.  
  340. void
  341. wmessage(prompt)
  342.     char *prompt;
  343. {
  344.     do_dialog(oklist(prompt), 2, 2, (char *)NULL);
  345. }
  346.  
  347. int
  348. waskync(prompt, def)
  349.     char *prompt;
  350. {
  351.     int emphasis;
  352.     int hit;
  353.     
  354.     switch (def) {
  355.     case 1:
  356.         emphasis= 2;
  357.         break;
  358.     case 0:
  359.         emphasis= 3;
  360.         break;
  361.     default:
  362.         emphasis= 4;
  363.         break;
  364.     }
  365.     
  366.     hit= do_dialog(ynclist(prompt), emphasis, 4, (char *) NULL);
  367.     
  368.     switch (hit) {
  369.     default: /* case 1: Return or Enter pressed */
  370.         return def;
  371.     case 2: /* Yes button */
  372.         return 1;
  373.     case 3: /* No button */
  374.         return 0;
  375.     case 4: /* Cancel button */
  376.         return -1;
  377.     }
  378. }
  379.  
  380. bool
  381. waskstr(prompt, buf, len)
  382.     char *prompt;
  383.     char *buf;
  384.     int len;
  385. {
  386.     /* This code assumes 'buf' is at least 256 bytes long! */
  387.     return do_dialog(editlist(prompt), 2, 3, buf) <= 2;
  388. }
  389.  
  390. void
  391. wperror(name)
  392.     char *name;
  393. {
  394.     char buf[256];
  395.     char *p= buf;
  396.     
  397.     if (name != NULL) {
  398.         strcpy(p, name);
  399.         strcat(p, ": ");
  400.         p += strlen(p);
  401.     }
  402.     strcat(p, "I/O error");
  403.     p += strlen(p);
  404.     sprintf(p, " %d", errno);
  405.     wmessage(buf);
  406. }
  407.